// The NSpring Framework for .NET
// Copyright (c) 2003, Jeffrey Varszegi
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions are met:
// 
// - Redistributions of source code must retain the above copyright notice, this 
// list of conditions and the following disclaimer.
// 
// - Redistributions in binary form must reproduce the above copyright notice, 
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 
// - Neither the name of the NSpring project nor the names of its contributors may
// be used to endorse or promote products derived from this software without 
// specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

namespace NSpring.Logging.Loggers {
    
using System;
using System.Collections;
using System.Diagnostics;

using NSpring.Logging.EventFormatters;

/// <summary>
/// A Logger implementation that writes to the Windows event log
/// </summary>
public sealed class WindowsEventLogger : Logger {
    private const string BLANK_STRING                   = "";
    private const string APPLICATION_LOG_SOURCE_NAME    = "application";
    private const string SECURITY_LOG_SOURCE_NAME       = "security";
    private const string SYSTEM_LOG_SOURCE_NAME         = "system";
    private static Hashtable protectedLogSourceNames    = new Hashtable(100);
    
    private const string LOG_EXTENSION                  = " Log";
    
    private static object staticMonitor                 = new object();
    
   // private string eventLogApplicationName              = null;
    private EventLog eventLog                           = null;

    //private string applicationName                      = null;

	private string eventLogSource						= null;
	private string eventLogName							= null;
    
    static WindowsEventLogger() {
        protectedLogSourceNames.Add(APPLICATION_LOG_SOURCE_NAME, APPLICATION_LOG_SOURCE_NAME);
        protectedLogSourceNames.Add(SECURITY_LOG_SOURCE_NAME, SECURITY_LOG_SOURCE_NAME);
        protectedLogSourceNames.Add(SYSTEM_LOG_SOURCE_NAME, SYSTEM_LOG_SOURCE_NAME);
    }
    
    /// <summary>
    /// Creates a new WindowsEventLogger instance
    /// </summary>
    /// <param name="_eventLogApplicationName">The Windows event log name</param>
	//public WindowsEventLogger(string _eventLogApplicationName) {
	//    ApplicationName = _eventLogApplicationName;
	//    IsBufferingEnabled = true;
	//    eventFormatter = new PatternEventFormatter("{message}");
	//}
	public WindowsEventLogger(string _eventLogSource, string _eventLogName)
	{
		EventLogSource = _eventLogSource;
		EventLogName = _eventLogName;
		IsBufferingEnabled = true;
		eventFormatter = new PatternEventFormatter("{message}");
	}
    
    /// <summary>
    /// Deletes the event log and source with the specified name.
    /// (The name should NOT end in " Log"-- this is automatically appended)
    /// </summary>
    /// <param name="eventLogApplicationName"></param>
    /// <returns>true if the deletion succeeded, false otherwise</returns>
    public static bool DeleteEventLog(string eventLogApplicationName) {
        if (eventLogApplicationName == null) {
            return false;
        }
        lock (staticMonitor) {
            eventLogApplicationName = eventLogApplicationName.Trim();
            try {
                EventLog.Delete(eventLogApplicationName + LOG_EXTENSION);
                EventLog.DeleteEventSource(eventLogApplicationName);
                return true;
            }
            catch {
                return false;
            }
        }
    }    
    
	//public string ApplicationName {
	//    get {
	//        return applicationName;
	//    }
	//    set {
	//        if (value == null) {
	//            throw new ArgumentNullException();
	//        }
	//        value = value.Trim();
	//        if (value.Equals("")) {
	//            throw new ArgumentException("The name must contain non-whitespace characters");
	//        }
	//        lock (monitor) {
	//            if (!isClosed) {
	//                throw new InvalidOperationException("Cannot set this property while the logger is open");
	//            }
	//            applicationName = value;
	//        }
	//    }
	//}
	public string EventLogSource
	{
		get { return eventLogSource; }
		set
		{
			if (value == null)
				throw new ArgumentNullException();
			value = value.Trim();
			if (value.Equals(""))
				throw new ArgumentException("The name must contain non-whitespace characters");
			lock (monitor)
			{
				if (!isClosed)
					throw new InvalidOperationException("Cannot set this property while the logger is open");
				eventLogSource = value;
			}
		}
	}
	public string EventLogName
	{
		get { return eventLogName; }
		set { eventLogName = value; }
	}
    
	//protected override void AcquireResources() {
	//    if (applicationName == null) {
	//        throw new ApplicationException("No application name set-- cannot open");
	//    }
        
	//    string v = applicationName.Trim();
	//    string vl = v.ToLower();
	//    if (vl.EndsWith(LOG_EXTENSION.ToLower())) {
	//        v = v.Substring(0, (v.Length - LOG_EXTENSION.Length)).Trim();
	//    }
	//    if (v.Equals(BLANK_STRING)) {
	//        throw new ApplicationException("Invalid application name");
	//    }
	//    else if (protectedLogSourceNames.ContainsKey(vl)) {
	//        throw new ApplicationException("The name '" + applicationName + "' is restricted from use for Windows event logging");
	//    }
	//    eventLogApplicationName = v;
        
	//    string logName = eventLogApplicationName + LOG_EXTENSION;
	//    try {
	//        if(!EventLog.SourceExists(eventLogApplicationName)){
	//            try {
	//                EventLog.CreateEventSource(eventLogApplicationName, logName);
                    
	//                // This delay is necessary due to a delay in registering a source on most systems
	//                try { System.Threading.Thread.Sleep(500); } catch {}
                    
	//            } catch {}
	//        }
	//    } catch (Exception e) {
	//        throw new ApplicationException("Couldn't create event source '" + eventLogApplicationName + "': " + e.GetType().FullName + ": " + e.Message);
	//    }

	//    try {
	//        eventLog = new EventLog();
	//        eventLog.Log = logName;
	//        eventLog.Source = eventLogApplicationName;
	//    } catch (Exception e) {
	//        throw new ApplicationException("Couldn't create event log: " + e.GetType().FullName + ": " + e.Message);
	//    }
	//}
	protected override void AcquireResources()
	{
		if (eventLogSource == null)
		{
			throw new ApplicationException("No application name set-- cannot open");
		}

		string v = eventLogSource.Trim();
		string vl = v.ToLower();
		//if (vl.EndsWith(LOG_EXTENSION.ToLower()))
		//{
		//    v = v.Substring(0, (v.Length - LOG_EXTENSION.Length)).Trim();
		//}
		if (v.Equals(BLANK_STRING))
		{
			throw new ApplicationException("Invalid application name");
		}
		else if (protectedLogSourceNames.ContainsKey(vl))
		{
			throw new ApplicationException("The name '" + eventLogSource + "' is restricted from use for Windows event logging");
		}
		eventLogSource = v;

		//string logName = eventLogApplicationName + LOG_EXTENSION;
		try
		{
			if (!EventLog.SourceExists(eventLogSource))
			{
				try
				{
					EventLog.CreateEventSource(eventLogSource, eventLogName);

					// This delay is necessary due to a delay in registering a source on most systems
					try { System.Threading.Thread.Sleep(500); }
					catch { }

				}
				catch { }
			}
		}
		catch (Exception e)
		{
			throw new ApplicationException("Couldn't create event source '" + eventLogSource + "': " + e.GetType().FullName + ": " + e.Message);
		}

		try
		{
			eventLog = new EventLog();
			eventLog.Log = eventLogName;
			eventLog.Source = eventLogSource;
		}
		catch (Exception e)
		{
			throw new ApplicationException("Couldn't create event log: " + e.GetType().FullName + ": " + e.Message);
		}
	}
    
    protected override void ReleaseResources() {
        try { eventLog.Close(); } catch {}
        eventLog = null;
    }

    protected override void Write(Event _event) {
        if (_event.Level == Level.Exception) {
            eventLog.WriteEntry(eventFormatter.Format(_event), EventLogEntryType.Error);
        }
        else if (_event.Level == Level.Warning) {
            eventLog.WriteEntry(eventFormatter.Format(_event), EventLogEntryType.Warning);
        }
        else {
            eventLog.WriteEntry(eventFormatter.Format(_event), EventLogEntryType.Information);
        }
    }
    
}
	
}
